
#define maxn  1000300
int n;
ll m;
struct node
{
	int x,y,z;
	node(){}
	node(int a,int b,int c){x=a; y=b; z=c;}
}a[maxn];
bool operator <(const node aa,const node bb)
{
	return aa.z>bb.z;
}
struct Node
{
	int x,y;
	Node(int a,int b){x=a; y=b;}
};
bool operator <(const Node aa,const Node bb)
{
	return aa.x<bb.x;
}
set<Node>st;
set<Node>::iterator it,tp,tp1,tp2;


int main()
{
#ifndef ONLINE_JUDGE
	freopen("in","r",stdin);
#endif
    int i,j,k;
	while(cin>>n>>m)
	{
		if((n||m)==0)	break;
		st.clear();
		int x,y,z;
		for(i=0; i<n; i++)//离散化z轴坐标
		{
			scanf("%d%d%d", &x,&y, &z);
			a[i]=node(x,y,z);
		}
		sort(a,a+n);
		/***************下面就是就立方体面积并不过有一点要注意的是这些立方体都是以（0,0,0）为一个坐标点，
		用set里面存储使该纵轴面积最大的矩形，按照x轴的递减大小排序，对应y轴递增，这样保证有唯一的矩形，x没有相同的，y也没有相同的***********************/
		st.insert(Node(0,inf));//加y轴一个边界
		st.insert(Node(inf,0));//加x轴一个边界
		ll ans=0,now=0;
		ll zz;
		i=0;
		while(i<n)//处理x和y轴
		{
			node  b=a[i];
			j=i;
			while(b.z==a[j].z && j<n)
			{
				j++;
			}
			for(int ni=i; ni<j; ni++)
			{
				
				Node q=Node(a[ni].x, a[ni].y);
				it=st.upper_bound(q);//求出比当前矩形 ,刚好大于x坐标的set里的矩形,
				if(it->y>=q.y)
					continue;
				
				tp=it;
				tp--;
				tp1=it;
				if(tp->x==q.x && tp->y>=q.y)
					continue;
				while(1)//维护set，使矩形最大
				{
					if(tp->y >=q.y)
					{
						now+=(ll)(q.x-tp->x)*(ll)(q.y - it->y);
						break;
					}
					else
					{
						now+=(ll)(q.x-tp->x)*(ll)(tp->y-it->y);
					}
					it--;
					tp--;
				}
				tp++;
				st.erase(tp,tp1);//当前矩形可以覆盖tp到tp1-1的矩形
				st.insert(q);
			}
			if(j==n)
			{
				ans+=now*(ll)b.z;
			}
			else
			{
				ans+=now*(ll)(b.z-a[j].z);
			}
			i=j;
		}
		cout<<m*m*m-ans<<endl;
	}
}

